package com.zhenai.rocyuan.modules.threadupdown.client;

import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.UnknownHostException;

import org.apache.log4j.Logger;

import com.zhenai.rocyuan.modules.threadupdown.BaseSocket;
import com.zhenai.rocyuan.modules.threadupdown.Users;
import com.zhenai.rocyuan.modules.threadupdown.Utils;

public class ClientMain {
	private ClientSocket cs = null;
	private String ip = BaseSocket.SERVER_HOSE;
	private int port = BaseSocket.SERVER_PORT;
	private String filePath;
	private Users user;
	private int loadPercent = -1;
	private static final Logger log = Logger.getLogger(ClientMain.class);

	/**
	 * 客户端启动入口
	 * 
	 * @param user
	 *            用户信息
	 */
	public ClientMain(Users user) {
		this.user = user;
	}

	/**
	 * 客户端与服务器通讯入口 <br>
	 * 注意：客户端可以根据最后返回的参数，来进行下一步操作，以保证本次需要从服务器下载的文件得以成功下载<br>
	 * 0: User is null<br>
	 * 1: 连接服务器失败<br>
	 * 2: User 验证失败[用户名或密码有误]<br>
	 * 3: 文件下载成功<br>
	 * 4: 文件下载失败<br>
	 * 5: 服务器端未找到相关Class<br>
	 * 6: 与服务器连接过程中出现传输异常<br>
	 * 
	 * @return
	 */
	public int work() {
		int returnFlag = 0;
		if (user == null) {
			return returnFlag;
		}
		ObjectOutputStream out = null;
		ObjectInputStream in = null;
		try {
			if (createConn()) {
				in = cs.getIn();
				out = cs.getOut();
				// 先检查服务器端发送过来的首次验证
				boolean flag = in.readBoolean();
				if (!flag) {
					log.debug("----服务器根据允许ip范围，拒绝本客户端继续连接");
				} else {
					// 发送验证数据到服务器
					this.cs.sendObject(user, out);
					out.flush();

					// 获取服务器验证返回的数据,根据返回的数据来判断是否进行下一步操作
					Object o = cs.getObject(in);
					Users u = null;
					if (o instanceof Users) {
						u = (Users) o;
						if (u.getUserName().equals(user.getUserName()) && u.getPassword().equals(user.getPassword())) {
							returnFlag = getFile(out, in);
						} else {
							returnFlag = 2;
							log.debug("---客户端[User]验证失败，服务器拒绝本客戶端继续连接");
						}
					}
				}
			} else {
				returnFlag = 1;
			}
		} catch (ClassNotFoundException e) {
			log.error(e, e);
			returnFlag = 5;
		} catch (IOException ex) {
			log.error(ex, ex);
			returnFlag = 6;
		} finally {
			this.cs.closeConnect();
		}
		return returnFlag;
	}

	private int getFile(ObjectOutputStream out, ObjectInputStream in) {
		int reFlag = 3;
		DataOutputStream fileOut = null;
		File saveFile = null;
		long passedlen = 0;
		long len = 0;
		try {
			BaseSocket.cc++;
			String fileName = in.readUTF();
			saveFile = new File(filePath, BaseSocket.cc + fileName);
			filePath = saveFile.getPath();
			if (!saveFile.getParentFile().exists()) {
				saveFile.getParentFile().mkdirs();
			}
			if (!saveFile.exists()) {
				saveFile.createNewFile();
			}
			len = in.readLong();

			// 断点续传的情况
			long skip = saveFile.length();
			out.writeLong(skip);
			out.flush();

			fileOut = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(saveFile, skip > 0 ? true : false)));
			log.debug("----client begin to receive file[len:" + len + "]");

			// 打开文件下载进度条,把原有下载的进度设置进去,此处暂停1s
			int oldPercent = (int) Utils.getPercent(skip, len);
			this.setLoadPercent(oldPercent);
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				log.error(e, e);
			}

			int bufferSize = 8192;
			byte[] buf = new byte[bufferSize];
			while (true) {
				int read = 0;
				if (in != null) {
					read = in.read(buf);
				}
				passedlen += read;
				int newPercent = (int) Utils.getPercent(passedlen, len);
				this.setLoadPercent(newPercent + oldPercent);
				if (read == -1) {
					this.setLoadPercent(100);
					break;
				}
				fileOut.write(buf, 0, read);
			}
			log.debug("----client receive ok,the file is " + saveFile.getPath());
			fileOut.flush();
			fileOut.close();
		} catch (IOException e) {
			reFlag = 4;
			log.error(e, e);
			log.debug("---中断与服务器连接，无法接收消息");
			if (fileOut != null) {
				try {
					fileOut.close();
				} catch (IOException e1) {
					log.error(e1, e1);
				}
			}
		}
		return reFlag;
	}

	/**
	 * 建立与服务器端的连接
	 * 
	 * @return
	 */
	private boolean createConn() {
		cs = new ClientSocket(ip, port);
		try {
			cs.getConnect();
			return true;
		} catch (UnknownHostException e) {
			log.error(e, e);
			return false;
		} catch (Exception e) {
			log.debug("----连接服务器失败-----");
			log.error(e, e);
			return false;
		}
	}

	/**
	 * 断开连接
	 */
	public void tearDownConnection() {
		if (cs != null) {
			cs.closeConnect();
		}
	}

	/**
	 * 获取下载文件的完整路径{path and fileName}
	 * 
	 * @return
	 */
	public String getDownloadFile() {
		return filePath;
	}

	/**
	 * 获取下载文件进度的百分比<br>
	 * 该属性值默认为-1,表明还没有开始下载或User信息验证不通过根本没有进入下载进程
	 * 
	 * @return
	 */
	public int getLoadPercent() {
		return this.loadPercent;
	}

	public void setLoadPercent(int loadPercent) {
		this.loadPercent = loadPercent;
	}

	public static void main(String arg[]) {
		for (int i = 0; i < 20; i++) {
			log.error("^^^^^^^" + i + "^^^^^^");
			Users user = new Users(); // BaseSocket.ERROR_NAME_PWD[0], BaseSocket.ERROR_NAME_PWD[1], null, null, 0
			final ClientMain client = new ClientMain(user);
			new Thread(new Runnable() {
				@Override
				public void run() {
					int b = client.work();
					log.error("^^^^^^^^^^^^^" + b);
				}
			}).start();
			// new Thread(new Runnable() {
			// @Override
			// public void run() {
			// boolean f = true;
			// while (f) {
			// if (client.getLoadPercent() == 100) {
			// f = false;
			// break;
			// }
			// }
			// }
			// }).start();

		}
	}
}